package com.example.calculator;

import com.example.model.RiskIndicator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * 风控指标计算器
 * 实现各种风控指标的计算逻辑
 */
@Slf4j
@Component
public class RiskIndicatorCalculator {

    /**
     * 计算交易风险指标
     *
     * @param userId 用户ID
     * @param transactionCount 交易次数
     * @param transactionAmount 交易金额
     * @param failedAttempts 失败尝试次数
     * @return 风险指标值和风险等级
     */
    public CalculationResult calculateTransactionRisk(String userId, int transactionCount, 
                                                     double transactionAmount, int failedAttempts) {
        log.debug("Calculating transaction risk for user: {}", userId);
        
        // 计算基础分数 (0-100)
        double baseScore = 50.0;
        
        // 交易次数因子 (频繁交易增加风险)
        double transactionFactor = Math.min(transactionCount / 10.0, 20.0);
        
        // 交易金额因子 (大额交易增加风险)
        double amountFactor = Math.min(transactionAmount / 1000.0, 30.0);
        
        // 失败尝试因子 (失败尝试增加风险)
        double failureFactor = Math.min(failedAttempts * 5.0, 40.0);
        
        // 计算最终风险分数
        double riskScore = baseScore + transactionFactor + amountFactor + failureFactor;
        riskScore = Math.min(riskScore, 100.0); // 确保不超过100
        
        // 确定风险等级
        RiskIndicator.RiskLevel riskLevel;
        if (riskScore < 30) {
            riskLevel = RiskIndicator.RiskLevel.LOW;
        } else if (riskScore < 60) {
            riskLevel = RiskIndicator.RiskLevel.MEDIUM;
        } else if (riskScore < 80) {
            riskLevel = RiskIndicator.RiskLevel.HIGH;
        } else {
            riskLevel = RiskIndicator.RiskLevel.CRITICAL;
        }
        
        // 构建额外属性
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("transactionCount", transactionCount);
        attributes.put("transactionAmount", transactionAmount);
        attributes.put("failedAttempts", failedAttempts);
        attributes.put("transactionFactor", transactionFactor);
        attributes.put("amountFactor", amountFactor);
        attributes.put("failureFactor", failureFactor);
        
        return new CalculationResult(riskScore, riskLevel, attributes);
    }
    
    /**
     * 计算登录风险指标
     *
     * @param userId 用户ID
     * @param loginAttempts 登录尝试次数
     * @param failedLogins 失败登录次数
     * @param unusualLocationLogin 是否有异常地点登录
     * @param unusualTimeLogin 是否有异常时间登录
     * @return 风险指标值和风险等级
     */
    public CalculationResult calculateLoginRisk(String userId, int loginAttempts, int failedLogins,
                                               boolean unusualLocationLogin, boolean unusualTimeLogin) {
        log.debug("Calculating login risk for user: {}", userId);
        
        // 计算基础分数 (0-100)
        double baseScore = 20.0;
        
        // 登录尝试因子 (频繁登录增加风险)
        double loginAttemptsFactor = Math.min(loginAttempts / 5.0, 15.0);
        
        // 失败登录因子 (失败登录增加风险)
        double failedLoginsFactor = Math.min(failedLogins * 10.0, 40.0);
        
        // 异常地点登录因子
        double locationFactor = unusualLocationLogin ? 25.0 : 0.0;
        
        // 异常时间登录因子
        double timeFactor = unusualTimeLogin ? 15.0 : 0.0;
        
        // 计算最终风险分数
        double riskScore = baseScore + loginAttemptsFactor + failedLoginsFactor + locationFactor + timeFactor;
        riskScore = Math.min(riskScore, 100.0); // 确保不超过100
        
        // 确定风险等级
        RiskIndicator.RiskLevel riskLevel;
        if (riskScore < 30) {
            riskLevel = RiskIndicator.RiskLevel.LOW;
        } else if (riskScore < 60) {
            riskLevel = RiskIndicator.RiskLevel.MEDIUM;
        } else if (riskScore < 80) {
            riskLevel = RiskIndicator.RiskLevel.HIGH;
        } else {
            riskLevel = RiskIndicator.RiskLevel.CRITICAL;
        }
        
        // 构建额外属性
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("loginAttempts", loginAttempts);
        attributes.put("failedLogins", failedLogins);
        attributes.put("unusualLocationLogin", unusualLocationLogin);
        attributes.put("unusualTimeLogin", unusualTimeLogin);
        attributes.put("loginAttemptsFactor", loginAttemptsFactor);
        attributes.put("failedLoginsFactor", failedLoginsFactor);
        attributes.put("locationFactor", locationFactor);
        attributes.put("timeFactor", timeFactor);
        
        return new CalculationResult(riskScore, riskLevel, attributes);
    }
    
    /**
     * 计算账户风险指标
     *
     * @param userId 用户ID
     * @param accountAge 账户年龄(天)
     * @param recentPasswordChange 最近是否修改密码
     * @param hasTwoFactorAuth 是否启用双因素认证
     * @param suspiciousActivities 可疑活动次数
     * @return 风险指标值和风险等级
     */
    public CalculationResult calculateAccountRisk(String userId, int accountAge, boolean recentPasswordChange,
                                                boolean hasTwoFactorAuth, int suspiciousActivities) {
        log.debug("Calculating account risk for user: {}", userId);
        
        // 计算基础分数 (0-100)
        double baseScore = 50.0;
        
        // 账户年龄因子 (新账户风险更高)
        double accountAgeFactor = Math.max(0, 30.0 - (accountAge / 10.0));
        
        // 密码修改因子 (最近修改密码降低风险)
        double passwordChangeFactor = recentPasswordChange ? -15.0 : 0.0;
        
        // 双因素认证因子 (启用双因素认证降低风险)
        double twoFactorAuthFactor = hasTwoFactorAuth ? -20.0 : 15.0;
        
        // 可疑活动因子 (可疑活动增加风险)
        double suspiciousActivitiesFactor = Math.min(suspiciousActivities * 8.0, 40.0);
        
        // 计算最终风险分数
        double riskScore = baseScore + accountAgeFactor + passwordChangeFactor + twoFactorAuthFactor + suspiciousActivitiesFactor;
        riskScore = Math.max(0.0, Math.min(riskScore, 100.0)); // 确保在0-100范围内
        
        // 确定风险等级
        RiskIndicator.RiskLevel riskLevel;
        if (riskScore < 30) {
            riskLevel = RiskIndicator.RiskLevel.LOW;
        } else if (riskScore < 60) {
            riskLevel = RiskIndicator.RiskLevel.MEDIUM;
        } else if (riskScore < 80) {
            riskLevel = RiskIndicator.RiskLevel.HIGH;
        } else {
            riskLevel = RiskIndicator.RiskLevel.CRITICAL;
        }
        
        // 构建额外属性
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("accountAge", accountAge);
        attributes.put("recentPasswordChange", recentPasswordChange);
        attributes.put("hasTwoFactorAuth", hasTwoFactorAuth);
        attributes.put("suspiciousActivities", suspiciousActivities);
        attributes.put("accountAgeFactor", accountAgeFactor);
        attributes.put("passwordChangeFactor", passwordChangeFactor);
        attributes.put("twoFactorAuthFactor", twoFactorAuthFactor);
        attributes.put("suspiciousActivitiesFactor", suspiciousActivitiesFactor);
        
        return new CalculationResult(riskScore, riskLevel, attributes);
    }
    
    /**
     * 计算结果类
     */
    public static class CalculationResult {
        private final double riskScore;
        private final RiskIndicator.RiskLevel riskLevel;
        private final Map<String, Object> attributes;
        
        public CalculationResult(double riskScore, RiskIndicator.RiskLevel riskLevel, Map<String, Object> attributes) {
            this.riskScore = riskScore;
            this.riskLevel = riskLevel;
            this.attributes = attributes;
        }
        
        public double getRiskScore() {
            return riskScore;
        }
        
        public RiskIndicator.RiskLevel getRiskLevel() {
            return riskLevel;
        }
        
        public Map<String, Object> getAttributes() {
            return attributes;
        }
    }
}